Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Add hardware ports and MW-FEM support #44

Merged
merged 35 commits into from
Jul 4, 2024
Merged

Conversation

nulinspiratie
Copy link
Contributor

@nulinspiratie nulinspiratie commented Jun 26, 2024

This PR introduces the concept of ports to QuAM, which can be passed as an argument to the channel. This solves certain issues such as the LF-FEM and OPX+ ports having different properties.
We also add MW-FEM support through the MWChannel,InMWChannel, and InOutMWChannel.

Channel Ports

In the section Channels, we have seen how to create analog channels and attach digital outputs to them.
In these examples, the ports are defined by the OPX output tuple (connector, port).
However, for more advanced use cases it is instead possible to define the ports using dedicated [Port][quam.components.ports.Port] QuAM components.
This is primarily useful in two situations:

  1. Multiple channels are connected to the same physical port, and the user wants to define the port and its properties only once.
  2. The user wants to access port-specific properties that cannot directly be accessed through the [Channel][quam.components.channels.Channel]. Examples are the crosstalk, delay, and sampling rate of the port.

Example: Defining a Port

In this example, we want to use analog output ("con1", 3) of the OPX+ to create a single channel.
We define the port using the [OPXPlusAnalogOutputPort][quam.components.ports.OPXPlusAnalogOutputPort] component, which allows us to set the offset and delay of the port.

from quam.components.ports import OPXPlusAnalogOutputPort
from quam.components import SingleChannel

port = OPXPlusAnalogOutputPort(port=("con1", 3), offset=0.2, delay=12)
channel = SingleChannel(opx_output=port)

Note that in this situation the port offset is defined by channel.port.offset, and is therefore part of the port.
The [SingleChannel][quam.components.channels.SingleChannel] component also has the attribute SingleChannel.OPX_output_offset, but its value is ignored in this case.
If we would have instead used SingleChannel.opx_output = ("con1", 3), then the offset would have been defined by channel.OPX_output_offset.

@nulinspiratie nulinspiratie changed the title Feat: Add hardware ports Feat: Add hardware ports and MW-FEM support Jun 28, 2024
from quam.components.ports import OPXPlusAnalogOutputPort
from quam.components import SingleChannel

port = OPXPlusAnalogOutputPort(port=("con1", 3), offset=0.2, delay=12)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit confusing as the term port has a few meanings here, it's both the class name (and therefore the returned type) that contains the offset and delay, and also it's an argument to the class, indicating the controller + port tuple (and FEM in OPX1000 case?)
I can think of several options:

  1. Name it channel - but this collides with the channel below, what is its purpose?
  2. Change the port argument, maybe we can have it physical_port? maybe we can also separate it from the tuple and just have: (controller=1, physical_port=3, offset_0.2,...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah there is some ambiguity here, agreed.

Channel is already reserved for everything in channels.py, they largely overlap with elements in the qua config. The reason I called it channel as opposed to element is that up to now they also implemented the controllers part of the config, so they were a combination of element + controller port. So I don't think channels would be a good name.

We could change the port argument to something else, but I'm not sure physical_port is the right name. The reason I liked using port as an argument is that from the channel's perspective you could say e.g. SingleChannel.opx_output.port.
I think separating it into controller, fem, and physical_port also adds too many parameters.
What about using port_id?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the object Port is actually the physical port + static configuration. Maybe we can keep it just as a port... or port_id as you suggested

I don't think that the existing tuple ('con1', 1, 1) makes a lot of sense, so it's weird to me it'll be the same in QuAM.
Note that at some point, the port tuple might change in QUA (probably separated similar to what I wrote above), so let's make sure we do not depend too strongly on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah interesting, do you also mean it will be changed in the qua config?
So in ("con1", 2, 3) what are the different parts called?
I also see in your example of where you separate it, you refer to con1 as controller=1, does that mean we'll go away from strings?

quam/components/ports.py Outdated Show resolved Hide resolved
quam/components/ports.py Outdated Show resolved Hide resolved
@nulinspiratie nulinspiratie merged commit 9e51f87 into main Jul 4, 2024
2 checks passed
@nulinspiratie nulinspiratie deleted the feat/ports branch July 4, 2024 06:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants